# 公众号H5-访问云托管服务
公众号H5调用,是指在公众号登录状态下进行的调用。如果公众号未登录则和普通网页一样,没有微信用户体系。
公众号登录需要遵守公众号-网页授权,目前情况下只有 已经微信认证的服务号
才可以完成下述登录鉴权流程。
另外需要注意,使用此方案实施登录,推荐前端页面放置在静态资源存储。目前云托管服务里动态服务提供页面目前已经支持,如果你的服务仍然表现是 Cannot GET /__wx__/oauth
,可以重新部署更新一下服务,使策略生效。
微信云托管服务目前以支持下述转发。 如果你使用自有服务器,或者其他非微信云托管提供公众号WEB分发服务,遇到
Cannot GET /__wx__/oauth
,可以在服务内(自有服务器或其他服务)配置转发规则,转发规则如下:
https://domain/__wx__/xxx -> https://servicewechat.com/wxa-qbase/xxx
location /__wx__/ {
proxy_pass https://servicewechat.com/wxa-qbase/;
}
# 使用优势(对比wx.request)
- 不耗费任何公网流量,前后端通信走内网;
- 天然免疫DDoS攻击,仅授权小程序/公众号可访问后端,其他人无法访问;
- 无视后端服务地域影响,没有跨地域延迟,后端无需多地部署;
- 无需配置「服务器域名」;
- 后端可直接获取用户信息。
因此,如果云托管服务只有微信小程序/公众号会调用,建议在服务设置中关闭公网访问。
# 使用前提
我们约定H5使用的公众号为A公众号
,如果你希望另外一个 B公众号
或者B小程序
的云托管环境也可以被 A公众号
访问,可以按照如下指引操作:
A公众号
和B公众号
/B小程序
同主体:需要配置资源复用A公众号
和B公众号
/B小程序
不同主体:推荐使用「微信开放平台-第三方平台」方式。A公众号
和B公众号
/B小程序
不同主体:将B公众号
/B小程序
视为「其他客户端」,通过公网访问。参考文档其他客户端-访问云托管服务。此方式下,B公众号
/B小程序
无法使用云调用/微信令牌,且需要配置「服务器域名」(使用云托管服务的默认公网域名/自定义域名均可)。
如果你对以上有任何建议和期待,欢迎在官方交流群联系我们。
# 基本使用
下述使用代码中,我们提供了一个JS模块 mplogin.min.js ,方便你可以直接调用就可以完成登录初始化,节省了你的接入成本。有一些注意点需要提前知晓:
- 云托管SDK在初始化前,需要自己登录过程,不兼容原生的登录;所以如果你使用了原生登录,请替换掉。
- SDK登录初始化时,页面将经过2-4次跳转,最终在页面栈中增加一级,mplogin模块自动处理回退了,如果想自己处理,可以传
noback:true
。 - mplogin模块可能不太适应部分框架型项目,会出现循环跳转的情况,有部分冲突,请在上线前在各种平台上充分测试,一般传
noback:true
可以解决大部分问题。 - mplogin不适合时,可参考此文档前后SDK方法,自行实现整个登录初始化过程。
- 下述方法每个页面的登录初始化是独立的,如果你的项目页面比较多,推荐使用独立登录页形式,减少初始化步骤,降低完成时间。
首先,在网页中引入如下3个JS文件
# 微信公众号SDK,用于使用前端公众号接口
https://res.wx.qq.com/open/js/jweixin-1.6.0.js
# 微信云服务SDK,用于调用微信云服务资源
https://web-9gikcbug35bad3a8-1304825656.tcloudbaseapp.com/sdk/1.3.0/cloud.js
# 封装的登录授权模块,用于一步完成授权登录步骤
https://web-9gikcbug35bad3a8-1304825656.tcloudbaseapp.com/sdk/1.3.1/mplogin.min.js
如果你因为业务原因,需要自己实现授权步骤,请参考此文档前后SDK方法。
然后在js中使用如下代码:
window.onload = async function () {
// 使用登录模块,传入信息开始授权登录过程
// 如果首次登录,页面会经历一系列跳转过程,请不要在登录前加业务处理代码,以免登录被中断。
const result = await window.mplogin({
scope: "snsapi_userinfo", // 必填,登录方式:snsapi_userinfo、snsapi_base
appid: 'wxaa01testenvid99', // 必填,公众号appid,将以此appid名义进行请求
// redirect: '', // 选填,授权成功后路由的地址,目标地址应能处理授权参数,不填为当前页面
envid: 'prod-testenvid', // 选填,资源方微信云托管环境,如果传递此参数则会返回初始化的cloud操作对象
resourceAppid: 'wxaa02testenvid99', // 选填,如果是资源复用模式,需要填环境共享下资源方微信账号
signature: window.location.href, // 选填,如果需要微信SDK的API方法,则填写要使用的地址,会返回signature签名对象,envid参数不填则无效。
// region: '' // 选填,环境的地域,可选ap-guangzhou、ap-beijing,不填默认为ap-shanghai
// traceUser:false // 选填,默认true,是否在将用户访问记录到用户管理中,非上海地域请设置成false
// noback: true // 选填,默认noback:false,此时初次跳转授权后,模块将重新回退加载页面。
// 由于CloudSDK在初次登录时需要多个页面跳转,最终带参返回页面在浏览器页面栈中多了一到两层
// 你可以根据业务自行用history处理上述问题,不需要模块介入则填noback:true
})
// 登录完成后,结果会以对象形式展示
/* 返回信息结构:
ret: number // 登录的状态
|_ -1: 参数错误,一般是appid缺失和scope类型有误
|_ 0: 成功
|_ 1: 当前页面或redirect页面非https协议,授权机制无法作用,请使用https协议
|_ 2: 系统判定有风险,阻止了此次登录,一般是授权耗时太长,导致过期了,清除缓存刷新可解决问题
|_ 3: 未引入微信WEBSDK,无法初始化cloud操作对象,或者因为环境未授权此账号使用。
msg: string // 登录失败的问题描述
cloud: object[function] // envid参数存在并成功初始化后,返回的操作函数对象
signature: object[string] // envid、signature参数存在并成功初始化后,返回的签名信息
info: string // 如果snsapi_userinfo登录,则会返回用户信息的cloudID,可以使用转换接口获取信息,见下文
*/
console.log(result)
if (result.ret === 0) { // ret为0时,代表登录已经完成,可以进行业务操作
window.app = result.cloud // result.cloud 返回初始化可操作的cloud函数对象,将其放置全局
// 向云托管服务发起调用
const callres = await window.app.callContainer({
path: '/xxx', // 填入业务自定义路径和参数,根目录,就是 /
method: 'POST', // 按照自己的业务开发,选择对应的方法
header: {
'X-WX-SERVICE': 'xxx', // xxx中填入服务名称(微信云托管 - 服务管理 - 服务列表 - 服务名称)
}
// 其余参数同 wx.request
})
console.log(callres)
// 使用微信公众号SDK,开始签名,签名信息在result.signature中
// 监听签名注册成功
wx.ready(function () {
// 发起网络类型获取,只是测试,可以替换自己想要的API方法
wx.getNetworkType({
success: function (res) {
window.alert('当前设备网络类型:'+res.networkType)
}
})
})
// 发起签名注册,是一个异步操作,成功会触发wx.ready
wx.config({
appId: 'wxaa01testenvid99', // 微信公众号appid
timestamp: result.signature.timestamp + '', // 时间戳,从返回result.signature中获取
nonceStr: result.signature.nonceStr, // 随机字符串,从返回result.signature中获取
signature: result.signature.signature, // 签名,从返回result.signature中获取
jsApiList: ['getNetworkType'] // 注册的api列表
})
} else { // ret不为0时,代表登录出现错误,一般出现在开发调试中,正式使用一般只有2-系统拦截错误
// 登录出现问题,打印问题描述
window.alert(result.msg)
}
}
snsapi_userinfo登录,会返回用户信息的cloudID,可参考此文档获取明文信息
如果你想深入了解 callContainer
的原理,建议阅读这篇文章
# 请求参数
callContainer
其他参数,直接参考 wx.request API,在这里列举常用参数:
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|---|
config.env | string | 是 | 云环境 ID | ||
path | string | 是 | 开发者服务器接口地址 | ||
data | string/object/ArrayBuffer | 否 | 请求的参数 | ||
header | Object | 是 | 设置请求的 header,header 中不能设置 Referer。content-type 默认为 application/json | ||
timeout | number | 否 | 超时时间,单位为毫秒。最大值不能超过15秒,否则无效 | ||
method | string | GET | 否 | HTTP 请求方法 | |
dataType | string | json | 否 | 返回的数据格式 | |
responseType | string | text | 否 | 响应的数据类型 | |
success | function | 否 | 接口调用成功的回调函数 | ||
fail | function | 否 | 接口调用失败的回调函数 | ||
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
如果希望 wx.cloud.container 返回 Promise,请勿传 success, fail 和 complete
# object.method 的合法值
值 | 说明 | 最低版本 |
---|---|---|
OPTIONS | HTTP 请求 OPTIONS | |
GET | HTTP 请求 GET | |
HEAD | HTTP 请求 HEAD | |
POST | HTTP 请求 POST | |
PUT | HTTP 请求 PUT | |
DELETE | HTTP 请求 DELETE | |
TRACE | HTTP 请求 TRACE | |
CONNECT | HTTP 请求 CONNECT |
# object.dataType 的合法值
值 | 说明 | 最低版本 |
---|---|---|
json | 返回的数据为 JSON,返回后会对返回的数据进行一次 JSON.parse | |
其他 | 不对返回的内容进行 JSON.parse |
# object.responseType 的合法值
值 | 说明 | 最低版本 |
---|---|---|
text | 响应的数据为文本 | |
arraybuffer | 响应的数据为 ArrayBuffer |
# 示例代码
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script src="https://web-9gikcbug35bad3a8-1304825656.tcloudbaseapp.com/sdk/1.3.0/cloud.js"></script>
<script src="https://web-9gikcbug35bad3a8-1304825656.tcloudbaseapp.com/sdk/1.3.1/mplogin.min.js"></script>
<script>
window.onload = async function () {
// 如果有需要,可以使用调试组件,在手机端查看
// const vConsole = new window.VConsole();
// 使用登录模块,传入信息开始授权登录过程
// 如果首次登录,页面会经历一系列跳转过程,请不要在登录前加业务处理代码,以免登录被中断。
const result = await window.mplogin({
scope: "snsapi_userinfo", // 必填,登录方式:snsapi_userinfo、snsapi_base
appid: 'wxaa01testenvid99', // 必填,公众号appid,将以此appid名义进行请求
// redirect: '', // 选填,授权成功后路由的地址,目标地址应能处理授权参数,不填为当前页面
envid: 'prod-testenvid', // 选填,资源方微信云托管环境,如果传递此参数则会返回初始化的cloud操作对象
resourceAppid: 'wxaa02testenvid99', // 选填,如果是资源复用模式,需要填资源方微信账号
signature: window.location.href // 选填,如果需要微信SDK的API方法,则填写要使用的地址,会返回signature签名对象,envid参数不填则无效
// region: '' // 选填,环境的地域,可选ap-guangzhou、ap-beijing,不填默认为ap-shanghai
// traceUser:false // 选填,默认true,是否在将用户访问记录到用户管理中,非上海地域请设置成false
// noback: true // 选填,默认noback:false,此时初次跳转授权后,模块将重新回退加载页面。
// 由于CloudSDK在初次登录时需要多个页面跳转,最终带参返回页面在浏览器页面栈中多了一到两层
// 你可以根据业务自行用history处理上述问题,不需要模块介入则填noback:true
})
// 登录完成后,结果会以对象形式展示
/* 返回信息结构:
ret: number // 登录的状态
|_ -1: 参数错误,一般是appid缺失和scope类型有误
|_ 0: 成功
|_ 1: 当前页面或redirect页面非https协议,授权机制无法作用,请使用https协议
|_ 2: 系统判定有风险,阻止了此次登录,一般是授权耗时太长,导致过期了,清除缓存刷新可解决问题
|_ 3: 未引入微信WEBSDK,无法初始化cloud操作对象,或者因为环境未授权此账号
msg: string // 登录失败的问题描述
cloud: object[function] // envid参数存在并成功初始化后,返回的操作函数对象
signature: object[string] // envid、signature参数存在并成功初始化后,返回的签名信息
info: string // 如果snsapi_userinfo登录,则会返回用户信息的cloudID,可以使用转换接口获取信息,见下文
*/
console.log(result)
if (result.ret === 0) { // ret为0时,代表登录已经完成,可以进行业务操作
window.app = result.cloud // result.cloud 返回初始化可操作的cloud函数对象,将其放置全局
// 向云托管服务发起调用
const callres = await window.app.callContainer({
path: '/xxx', // 填入业务自定义路径和参数,根目录,就是 /
method: 'POST', // 按照自己的业务开发,选择对应的方法
header: {
'X-WX-SERVICE': 'xxx', // xxx中填入服务名称(微信云托管 - 服务管理 - 服务列表 - 服务名称)
}
// 其余参数同 wx.request
})
console.log(callres)
// 使用微信公众号SDK,开始签名,签名信息在result.signature中
// 监听签名注册成功
wx.ready(function () {
// 发起网络类型获取,只是测试,可以替换自己想要的API方法
wx.getNetworkType({
success: function (res) {
window.alert('当前设备网络类型:'+res.networkType)
}
})
})
// 发起签名注册,是一个异步操作,成功会触发wx.ready
wx.config({
appId: 'wxaa01testenvid99', // 微信公众号appid
timestamp: result.signature.timestamp + '', // 时间戳,从返回result.signature中获取
nonceStr: result.signature.nonceStr, // 随机字符串,从返回result.signature中获取
signature: result.signature.signature, // 签名,从返回result.signature中获取
jsApiList: ['getNetworkType'] // 注册的api列表
})
} else { // ret不为0时,代表登录出现错误,一般出现在开发调试中,正式使用一般只有2-系统拦截错误
// 登录出现问题,打印问题描述
window.alert(result.msg)
}
}
</script>
# 后端直接获取用户信息
公众号向云托管服务发起callcontainer调用时,你的服务请求header中会自动带有用户信息,包括openid、unionid、ip地址、可信来源等等,无需再通过小程序wx.login登录,然后调接口置换,大幅简化了流程。
注意,资源复用情况下,获取openid的字段和普通获取不一致。
# 使用限制
- 请求大小限制100K(请求中不建议包含图片,可通过对象存储处理);
- 返回包大小限制 1000k。
# 常见报错
错误码 | 原因 |
---|---|
-601012 | 环境不属于该公众号,或者没有资源复用给该公众号 |
-601034 | 公众号是测试号或者其他类型的变形账号,不符合要求,请使用已认证的服务号(非订阅号) |
-601013 | 当前公众号账号为受限类型,一般不会出现,如果存在请提交工单处理 |